-
Notifications
You must be signed in to change notification settings - Fork 106
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
docs(0009): upgrade SPSP for PSK2 #367
Conversation
| `balance` | Object | _(OPTIONAL)_ Details of this receiver's balance. Used for invoices and similar temporary accounts. | | ||
| `balance.maximum` | Integer String | Maximum amount, denoted in the minimum divisible units of the ledger, the receiver will accept. This represents the highest sum that incoming chunks are allowed to reach, not the highest size of an individual chunk (which is determined by path MTU). If this is an invoice the `balance.maximum` is the amount at which the invoice would be considered paid. | | ||
| `balance.current` | Integer String | Current sum of all incoming chunks. | | ||
| `ledger_info` | Object | _(OPTIONAL)_ Details about the destination ledger, for sender's display purposes. | | ||
| `ledger_info.currency_code` | String | Currency code to identify the receiver's currency. Currencies that have [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) codes should use those. Sender UIs SHOULD be able to render non-standard codes | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be asset_code
and asset_scale
. In case people want to use non-currency assets.
## Appendix A: (Optional) Webfinger Discovery | ||
|
||
Whenever possible, receiver URLs should be exchanged out-of-band and discovery should be skipped. However, in some cases, it may be useful to have a standardized user-friendly identifier. This discovery method describes how to resolve such an identifier to an SPSP endpoint. | ||
## Appendix A: (Deprecated) Webfinger Discovery |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should remove this section.
``` http | ||
GET /api/spsp/bob HTTP/1.1 | ||
Host: red.ilpdemo.org | ||
Accept: application/json | ||
Accept: application/x-spsp-response |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should be Accept: application/spsp+json
and we should get a provisional registration.
The SPSP endpoint is a URI used by the sender to query information about the receiver and set up payments. The SPSP endpoint URI MAY NOT contain query string parameters. The sender SHOULD treat the URI as opaque. There are several supported ways to refer to an SPSP endpoint: | ||
|
||
- [Payment-pointer](#appendix-b-payment-pointer) (Recommended) `$alice.example.com` or `$example.com/bob`. This SHOULD be the only kind of SPSP identifier exposed to users. | ||
- [Webfinger acct](#appendix-a-deprecated-webfinger-discovery) (Deprecated) `alice@example.com`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We shouldn't have two types of identifiers. if we're adding the payment pointers, let's get rid of the webfinger identifiers.
|
||
This is the recommended way to identify an SPSP receiver, and is intended to be the main form of identifier that users on Interledger will interact with. It can be used as a persistent identifier for a person or as a temporary identifier to represent an invoice, much like a bitcoin address. | ||
|
||
The payment pointer is in the form `$example.com/bob` (A payment pointer with no path is also acceptable, i.e. `$bob.example.com`). This is converted into an SPSP URI. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should specify the exact format for payment identifiers. For example, are ?
allowed? Hashes (#
) presumably aren't. Is URL encoding (e.g. %20
) supported? Presumably, parsing stops at the first space character? Can a payment identifier end in a period (.
)? (We may want to say no to avoid ambiguity when parsing identifiers from text like: Hi everyone, my identifier is $justmoon.com/big-money.
)
|
||
Whenever possible, receiver URLs should be exchanged out-of-band and discovery should be skipped. However, in some cases, it may be useful to have a standardized user-friendly identifier. This discovery method describes how to resolve such an identifier to an SPSP endpoint. | ||
The payment pointer is in the form `$example.com/bob` (A payment pointer with no path is also acceptable, i.e. `$bob.example.com`). This is converted into an SPSP URI. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I kind of like the $example...
format and hear the criticism of the email-style identifier, but having it start with a dollar sign makes it quite US-centric. It's unfortunate that there is no widely-recognized symbol that just means "money" or "currency" without being tied to a specific one.
@diminator, @adrianhopebailie, @earizon, @michielbdejong, @oniabifo, @nathanawmk have any thoughts about this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Most keyboards have the $
, at least. It also has the connotation of being a variable that expands to something else, which is cool (it 'expands' to your ILP address)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How do you feel about the name "Payment Pointer" for it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typical American. You adopt the $
sign for your currency and suddenly it's "US-centric". ;)
The most common hypothesis for the origin of $
according to Wikipedia:
The symbol was adopted by Charles V and was part of his coat of arms representing Spain's American possessions. The symbol was later stamped on coins minted in gold and silver. The coin, also known as Spanish dollar, was the first global currency used in the entire world since the Spanish Empire was the first global Empire.
So, if anything it's Spanish Empire-centric, not US-centric.
As a result, no other symbol is used by as many different currencies:
Australian (A$), Bahamian (B$), Barbadian (Bds$), Belizean (BZ$), Bermudian (BD$), Brunei (B$), Canadian (Can$), Cayman Islands (CI$), East Caribbean (EC$), Fiji (FJ$), Guyanese (G$),[5] Hong Kong (HK$/元/圓), Jamaican (J$), Kiribati, Liberian (L$), Linden Dollar (Second Life virtual world) (L$ or LD$), Namibian (N$), New Zealand (NZ$), Singaporean (S$), Solomon Islands (SI$), Surinamese (SRD), Taiwanese (NT$/元/圓), Trinidad and Tobago (TT$), Tuvaluan, United States (US$), and Zimbabwean (Z$) dollars
Argentine, Chilean (CLP$), Colombian (COL$), Cuban (
$MN), Cuban convertible (CUC$ ), Dominican (RD$), Mexican (Mex$), and Uruguayan ($U) pesos
It also appears in the currency symbols for Brazilian Real (R$) and Nicaraguan córdoba (C$) among a few others. That means there are people on every continent who recognize $
as the symbol for their currency. No other currency symbol comes close. You could make a case for ¥
which I would guess is the currency symbol used by the most people. But it is used only by two currencies: Chinese Renminbi yuan and Japanese yen, so I don't think you can make a strong case that it is the best global choice. There is the "generic currency sign" ¤
, but nobody would recognize that thing.
There are of course also pragmatic reasons for using $
. It's an IA5 character and therefore easily encoded and included in pretty much all keyboard layouts worldwide. We should check if that is still true for mobile input methods.
Is the $
perfect? No. It's not. Ideally, something like ¤
would be an IA5 character and widely recognized. But we're in the real world and out of the available choices, the $
has a huge lead. Someone patriotic whose country uses a different symbol might think it's associated with the US and feel excluded. If anyone has a solution for that, let me know. But I also think there will be a lot of people that wouldn't react that way. Speaking as a German, the $
to me just means money. The fact that the US adopted it is just another example of a young country that's perhaps lacking a little bit of cultural identity. And the fact that Americans would be worried that the $
is not culturally neutral is an example of maybe a little bit of lack of cultural awareness - the majority of people whose local currency symbol is or includes the $
are not Americans. The US is just one of several countries that used $
because they didn't have their own historic currency symbol and $
was basically the international symbol for money at the time.
b637b3e
to
4fb29c0
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
see ^
"balance": { | ||
"maximum": "100000", | ||
"current": "5360" | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a fundamental change, you're not looking up data about a person, but about an invoice. Although that may be useful by itself, that's not what we use spsp for in ilp-kit.
Can't we keep it so the sender determines the amount, like it's now in ilp-kit? Also, we need to display name and avatar.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The balance
object is only present if this represents an invoice. The sender can still determine the amount; in the case of an invoice it will start to raise the current balance until it reaches the maximum, and if it's just an ordinary receiver then they'll just accept funds no matter what.
The name and avatar URL are still present in the receiver_info
object. They're not required fields, though, because not everyone may want to display that information.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure we need the current balance, even for invoices. In PSK2 the receiver tells the sender with every chunk how much of the total has arrived so far. I think it's more likely that you'd use that mechanism to figure out how close it is to being paid, rather than repeatedly querying the HTTP endpoint.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You may want to see the current amount paid before you start trying to pay the invoice, though
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is a partially paid invoice something you'd expect to see regularly? It seems like that's more likely to be caused by something going wrong with a chunked payment half-way.
That also reminded me, is there a case to me made for using a specific payment ID in the PSK packet that's related to the invoice, or is the assumption that you would include the type of identifying information in the ILP address that SPSP returns?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you would probably use the ILP address to encode that information. However, when I upgraded http-ilp for PSK2, I used the payment ID as the Pay-Token
rather than putting it in the PSK2 application data. Using the ILP address is a third option. We might want to decide which of those is the recommended option.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Evan, FWIW, partially paid invoices are a common business scenario, even aside from failed or incomplete payments.
I would say the $ sign is the closest sign to a world currency. As a Nigerian, i do not think the Naira Sign '₦' is available on any keyboard out there, even the keyboards back home do not have them. I have to make use of google to copy the code whenever i want to make use of it. I checked the Iphone keyboard layouts also, and there are only Dollars, Euro, and pounds sign available. Most Nigerians, and even every African that i have met recognizes dollars as the world currency. |
"balance": { | ||
"maximum": "100000", | ||
"current": "5360" | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure we need the current balance, even for invoices. In PSK2 the receiver tells the sender with every chunk how much of the total has arrived so far. I think it's more likely that you'd use that mechanism to figure out how close it is to being paid, rather than repeatedly querying the HTTP endpoint.
|
||
Whenever possible, receiver URLs should be exchanged out-of-band and discovery should be skipped. However, in some cases, it may be useful to have a standardized user-friendly identifier. This discovery method describes how to resolve such an identifier to an SPSP endpoint. | ||
Adding this subdomain allows you to use `$example.com` as your payment pointer, even if the actual `example.com` is running a website via a CDN like github pages. The SPSP traffic will go to `spsp.example.com`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How would that work with Github pages? Doesn't it use https://{username}.github.io/{repo}
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use a CNAME record to make your own domain point to your github pages. Then you put that domain behind something like cloudflare, so the CNAME resolve after the HTTPS is terminated (that way github doesn't need a cart for your site)
|
||
Note that the sender can send as many payments as they want using the same receiver info. The sender SHOULD query the receiver again once the time indicated in the [`Cache-Control` header](#response-headers) has passed. | ||
This is the recommended way to identify an SPSP receiver, and is intended to be the main form of identifier that users on Interledger will interact with. It can be used as a persistent identifier for a person or as a temporary identifier to represent an invoice, much like a bitcoin address. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is the main identifier people are going to interact with, I think it definitely needs some version negotiation in the resolution protocol. We're not going to want to change the identifier so we should plan for different versions of SPSP and/or PSK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right now, $bob.example.com
resolves to https://spsp.bob.example.com
, with the accept header application/spsp+json
. The response returned has a content type of application/spsp+json
as well.
If we want to add a breaking version to the protocol, we can either:
-
change the subdomain (SPSP goes to
spsp.bob.example.com
but new SPSP goes tospsp-v4.bob.example.com
. -
change the accept header (SPSP is returned when the accept header is
application/spsp+json
but SPSPv4 is returned forapplication/spspv4+json
. -
(potentially combined with 2) return a content type of
application/spspv4+json
in theContent-Type
response, allowing the client to check and make sure that it received a supported SPSP version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this is the main identifier people are going to interact with, I think it definitely needs some version negotiation in the resolution protocol.
The resolution of an endpoint to query based on the identifier needs to be simple and stable. The interaction with the endpoint can then accommodate versioning (sent in the request headers, list of versioned endpoints in the initial response etc)
|
||
## Appendix A: (Optional) Webfinger Discovery | ||
The payment pointer is in the form `$example.com/bob` (A payment pointer with no path is also acceptable, i.e. `$bob.example.com`). This is converted into an SPSP URI, by removing the `$` and replacing it with `https://spsp.`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would you read this as "pay bob dot example dot com"?
If you have your own domain, this format seems pretty good: "pay sharafian dot com".
I'm less sure about the experience for people that are addressed in terms of their provider. Email addresses read nicely as "evan at provider dot com". At seems a sensible way to indicate that it's a user with a certain provider (or maybe I'm just used to that now). "pay evan dot provider dot com" sounds a little less nice to me, maybe because I'm not really used to the dot separating the username from the provider. "pay provider dot com slash evan" is even worse, in my opinion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Email addresses have their quirks too; I think having our identifiers structured similar to web URLs makes them easier to understand. It also looks a little more like a modern handle-style identifier like @example
, while example@example.com
feels a little more dated (maybe just to me).
It's nice having the clear delineation between user and provider, but that also precludes the ability to have a short vanity address (ie. $sharafian.com
instead of pay@sharafian.com
) which I think is cool.
As for the path, I would imagine it would be used more commonly for things like invoices. Something like $invoice.amazon.com/22589235
might read better than $22589235.invoice.amazon.com
. It also helps us support people whose systems might not be easily set up to handle subdomains dynamically.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think having our identifiers structured similar to web URLs makes them easier to understand
This has not been true historically. The WebID standard has tried for a decade to get people to identify themselves using a URL with very little success.
It also looks a little more like a modern handle-style identifier like @example
That's why Square used the CashHash format $user
. The problem is that this is a domain-less identifier. You need to have a way to scope it.
example@example.com feels a little more dated (maybe just to me)
It's a compromise. If you've got the network effect of Twitter you can have an implicit domain but even then it doesn't always work: Does @sharafian mean https://twitter.com/sharafian or https://github.com/sharafian ?
@@ -148,46 +168,51 @@ Content-Type: application/json | |||
|
|||
### Payment Setup |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are there use cases where you might want to send data along with the PSK payment? If so, SPSP should specify a format for the PSK data field.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not quite sure on this one. Supporting something like "source identifier" or "payment memo" might be useful. But there's a lot of use cases where we don't need that, so I think whatever we do I'd like to have the option to leave the application data blank.
So after some implementation work, I noticed a problem with our subdomain method: If you're It would be impractical to manually create a cert for each user in order to allow The easy solution is to make your user's identifier The reason we prepend (@michielbdejong I remember you talking about some sort of dynamic SSL certs thing at one point; is that at all applicable to the situation I'm talking about?) |
yes, with letsencrypt your server can register certs whenever it needs them, but there's a rate limit of something like 5 a week per server, I think. |
@sharafian i was able to use letsencrypt to get ssl certs for my subdomain but it seems to expire every three months so has to be renewed. |
That is why I strongly recommend not mis-using subdomains in this way. Subdomains are a reverse heirarchy. I recommend the scheme I suggested in interledgerjs/ilp#126 (comment) The scheme supports both "hosted" and "vanity" pointers and is actually pretty easy to host, even on Github pages. For a hosted account (let's say it is hosted by No need for the host to have additional SSL certs and unlikely to have conflicts on the path starting with For a vanity pointer (e.g. I have my own domain, let's use It took me 30 seconds to set that up on Github pages with no Letsencrypt, DNS or other tweaks. If you hit that URL now you'll get a static SPSP response. |
Github gives each user a subdomain so I don't think there's anything inherently wrong with the approach. It's just that adding a hard-coded domain segment won't be feasible.
How do you pronounce Additionally,
Because ILP addresses are liable to change frequently and a shared secret needs a live PSK2 receiver, it won't really be feasible to statically host an SPSP response. That means if you want I agree that it's important to be able to set up an SPSP receiver without running your own infrastructure: the big advantage of having SPSP on a separate subdomain is that you can have a CNAME record to point that at a service to act as an SPSP receiver for you. For instance, you can make the following records:
That allows me to have a personal website and an SPSP receiver on my domain without running a single server myself. All of that could be done through a service like cloudflare. One thing that we could do would be to resolve
The reason I don't like that is that it prioritizes the addresses of people with their own domains over people who have a personal subdomain on a provider (the Another option would be to resolve the DNS for the host (i.e. |
They give users a subdomain under a completely different TLD though. That's not by accident. Partitioning the traffic between Having a per-user subdomain is not a bad thing per se, but having the subdomains below a TLD that has a completely different purpose is a recipe for disaster.
That's was my point. You are breaking the domain hierarchy. If the purpose of the domain is to express "Bob's account on the SPSP service hosted at red.ilpdemo.org" then the domain needs to be The hardcoded subdomain is a bad idea. Don't do it. FYI: I'm sure there are some good mail archives at the IETF that detail specifically why using hard-coded subdomains is a bad idea, if you're interested. They'll likely revolve around the development of RFC5785 which defines a hardcoded path prefix instead.
Surely how you pronounce this is not as important as the practicality of implementing it!? Personally, for "$adrianhopebailie.github.io", I would say: "Pay adrianhopebailie dot github dot io" and for "bob$red.ilpdemo.org" I would say: "Pay bob at red dot ilpdemo dot org". It's an account at a host, the fact that it's a payment tells you that the separator to use is a
Why is it strange? It's a perfectly valid URL. Users will never type
If you can't have a static SPSP response I'd consider SPSP dead-in-the-water for many use cases then. I should be able to host a static response that at least redirects the client to a live endpoint. Requiring people to manage DNS in order to setup a personal service has proven historically to always be a failure.
My proposal doesn't preclude you from doing that. Assuming you have the same DNS entries above you can use Interestingly, another advantage of having all SPSP endpoint paths start with |
I completely disagree there; If we didn't care about how users read this identifier we could use any one of our less easily recognizable identifiers: The reason I'm arguing so vehemently to keep the
I absolutely agree; we shouldn't require users to run their own servers just to participate in SPSP. Not sure why using DNS for vanity addresses is a problem, though. It's exactly the same as email; you can sign up for a provider without personally setting anything up, but if you want your personal site to be your email address, you have to add a couple MX records.
If we're not adding another subdomain segment, we really don't need to have a separate account portion. We could just say that The only case where A server providing multiple SPSP receivers could easily use this URL to generate an SPSP response for bob; in fact, I already have a working implementation of that: https://github.com/sharafian/ilp-plugin-outgoing-settle/blob/master/index.js#L73 This was the original proposal and the reason we switched from it was that @justmoon brought up the point that it made it impossible for someone hosting their personal site with something like cloudflare and github pages to ever host an SPSP receiver for their personal site's domain (in his case
That's an interesting point. What if we combined the two approaches, such that
@justmoon @adrianhopebailie @emschwartz, how do you feel about that proposal? |
You are confusing how users read the identifier with selecting a recognizable identifier. They are not the same thing. We need to pick a recognizable format (hence we can't use Once we have a recognizable format people will figure out how to read/say it that makes sense. I agree that using a URI is not attractive and not concise which is why those are off the table.
I agree 100% with that format but I think it compromises versatility too much. I think that same format but with an optional
No exactly. MX records are not CNAME records, they are specifically for mail services. They allow you to host two services at the SAME domain. This makes it easy for email providers to scale up to millions of accounts because the way you resolve a mail exchanger from DNS is designed to scale. You can have multiple servers at different domains and even set a priority for them all using a handful of DNS records. What you are suggesting is that an SPSP provider that hosts SPSP services for many accounts will need to have a wildcard DNS record that captures all DNS requests for subdomains. It will work but you'd never be able to host the SPSP services on the same domain as other services (similarly to how Github has user subdomains on Unless... You have a hardcoded path (like NOTE: Doing this so late in the flow means you have to use the same TLS certs for WWW and SPSP services because the TLS handshake is complete before the request comes in. This is hard to get around without an explicit DNS level scaling solution like MX records. (May be worth looking at SRV records but that gets ugly because it requires clients to perform DNS queries). I think your compromise proposal is good but I still like the path Something to consider is that my proposal is identical to yours but with an additional option giving SPSP hosts the option to offer their users a So in summary, I propose we support the following:
If we aren't going to use the |
On re-reading this I think maybe allowing a path segment in the pointer is a good idea, that would mean no need for the account segment.
|
That last proposal sounds good to me. Only thing I'm not sure is whether we should do the Also not sure if |
I think we'd be better off supporting versioning through headers than hardcoding new versions as new paths. This also means we decouple this protocol (resolution of a URL from a pointer) from SPSP. None of the registered
I think it's problematic to have different behaviour specified for the endpoint depending on whether there is a path or not. We should keep this as simple as possible. I also think it's useful to require the To that end, I think using the
All requests to these endpoints should have an We could also extend this standard in future to have pre-flight requests to that URL for protocol and version detection. (i.e. Using an OPTIONS request instead of a GET) By the way there is also an interesting protocol called POSH which may be a good way to have hosted SPSP endpoints for custom domains but on a single host (where the host doesn't have to deploy certs for each domain): https://tools.ietf.org/html/rfc7711 |
This all sounds good to me. I like the idea of just having the SPSP receiver software change for version updates, without the resolution logic changing at all.
I disagree here. I'd just explain it by saying "The default path is |
This would still follow the standard, note that the I'll try and capture this in a new IL-RFC but I think the protocol is basically this: The ABNF definition of a payment pointer is:
If A payment setup service MUST be accessible at the URL: ===================== Side note: One of the features of So the question is, what should I expect to find at Maybe something to add in time. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In 2017 I would have said "don't just change stuff around", but my new approach it to embrace whatever experiments people in the Interledger community want to conduct, so I'll make sure the Interledger testnet supports these new ideas, and see if I can write a tutorial that uses your new format! :) Just:
-
clarify whether the meaning of payment pointers like
$example.com/alice
is the one from line 64 (https://example.com/spsp/alice
) or the one from line 185 (https://spsp.example.com/alice
), and whether$alice.example.com
is allowed as an alternative format or not. -
Consider removing ledger_info, or if not, at least also change it to asset_* on lines 94 and 95.
7. The receiver MAY submit the incoming payment to an external system for review to ensure that the funds are wanted. | ||
8. If the payment is expected, the receiver's PSK module submits the condition fulfillment to the ledger to execute the transfer. If not, the PSK module rejects the incoming transfer. | ||
9. If the receiver executed the transfer, the sender's SPSP client receives a notification from its ILP module that the transfer has been executed, including the condition fulfillment from the receiver, and notifies the sender that the payment is completed. If the receiver rejected the transfer, the sender's SPSP client receives a notification with the receiver-specified error message detailing why the payment was rejected. | ||
4. The sender uses PSK2 to generate the payment chunk and format additional data intended for the reciever to be sent with the payment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reciever
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just one chunk? maybe say 'the first payment chunk'?
8. If the payment is expected, the receiver's PSK module submits the condition fulfillment to the ledger to execute the transfer. If not, the PSK module rejects the incoming transfer. | ||
9. If the receiver executed the transfer, the sender's SPSP client receives a notification from its ILP module that the transfer has been executed, including the condition fulfillment from the receiver, and notifies the sender that the payment is completed. If the receiver rejected the transfer, the sender's SPSP client receives a notification with the receiver-specified error message detailing why the payment was rejected. | ||
4. The sender uses PSK2 to generate the payment chunk and format additional data intended for the reciever to be sent with the payment. | ||
5. The sender sends a prepare packet to a connector with the condition and ILP address attached. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
attached how?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not really "attached" anymore since those fields are just in the packet
5. The sender sends a prepare packet to a connector with the condition and ILP address attached. | ||
6. The receiver's PSK2 module registers the incoming packet, parses, and validates the ILP packet. | ||
7. The receiver MAY submit the incoming packet to an external system for review to ensure that the funds are wanted. | ||
8. If the payment is expected, the receiver's PSK2 module replies with a fulfillment packet. If not, the PSK2 module replies with a reject packet. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe mention that it used PSK2 to derive the fulfillment from the prepare and/or its memory of the shared secret it gave out?
|
||
## Specification | ||
|
||
The SPSP endpoint is a URI used by the sender to query information about the receiver and set up payments. The SPSP endpoint URI MAY contain query string parameters. The sender SHOULD treat the URI as opaque. | ||
The SPSP endpoint is a URI used by the sender to query information about the receiver and set up payments. The SPSP endpoint URI MAY NOT contain query string parameters. The sender SHOULD treat the URI as opaque. There are several supported ways to refer to an SPSP endpoint: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
information about the receiver or receiver's invoice
|
||
## Specification | ||
|
||
The SPSP endpoint is a URI used by the sender to query information about the receiver and set up payments. The SPSP endpoint URI MAY contain query string parameters. The sender SHOULD treat the URI as opaque. | ||
The SPSP endpoint is a URI used by the sender to query information about the receiver and set up payments. The SPSP endpoint URI MAY NOT contain query string parameters. The sender SHOULD treat the URI as opaque. There are several supported ways to refer to an SPSP endpoint: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"MAY NOT" is not defined by https://www.ietf.org/rfc/rfc2119.txt, do you mean 'MAY' as in 'presence and absence are both allowed', or 'SHOULD NOT' as in 'only absence is allowed, unless you have a good reason to override this'?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, I meant MUST NOT
The SPSP endpoint is a URI used by the sender to query information about the receiver and set up payments. The SPSP endpoint URI MAY NOT contain query string parameters. The sender SHOULD treat the URI as opaque. There are several supported ways to refer to an SPSP endpoint: | ||
|
||
- [Payment-pointer](#appendix-a-payment-pointer) (Recommended) `$alice.example.com` or `$example.com/bob`. This SHOULD be the only kind of SPSP identifier exposed to users. | ||
- Raw endpoint URI (Not recommended) `https://example.com/spsp/alice`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe explicitly explain that, since dots are not allowed in the path after /spsp/
, $michiel.ilp.michielbdejong.com translates to https://ilp.michielbdejong.com/spsp/michiel and never to https://michielbdejong.com/spsp/michiel.ilp.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually $michiel.ilp.michielbdejong.com
now becomes https://michiel.ilp.michielbdejong.com/.well-known/pay
, while $michielbdejong/spsp/michiel.ilp
becomes https://michielbdejong/spsp/michiel.ilp
.
| `balance.current` | Integer String | Current sum of all incoming chunks. | | ||
| `ledger_info` | Object | _(OPTIONAL)_ Details about the destination ledger, for sender's display purposes. | | ||
| `ledger_info.asset_code` | String | Asset code to identify the receiver's currency. Currencies that have [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) codes should use those. Sender UIs SHOULD be able to render non-standard codes | | ||
| `ledger_info.asset_scale` | Integer | The scale of the amounts on the destination ledger (e.g. an amount of `"1000"` with a scale of `2` translates to `10.00` units of the destination ledger's asset/currency) | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the rename from currency_{code,scale} to asset_{code,scale}? Did the meaning stay the same?
I think these fields should now be optional, if defined at all. In PSK2, there no longer is a concept of destination ledger unit pegging (currency_code/currency_scale), because there are no more curves in route broadcasts, right? Destination ledger units are now only relevant for expressing the percentage of an invoice that is paid by one chunk. Also, they were already a problem because they allow the receiver to manipulate them, and pretend to be a cheap shop on an expensive network.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Those fields are now optional, and I've renamed from ledger_info
to asset_info
. I see your point about manipulation by the receiver, but I'm not seeing it as an attack vector unless the sender doesn't check the source amount at all. It could make the network as a whole look bad, but that will always be a problem when you quote by destination amounts because the receiver could always put their receiver after a highly expensive connector which they control.
"balance": { | ||
"maximum": "100000", | ||
"current": "5360" | ||
}, | ||
"ledger_info": { | ||
"currency_code": "USD", | ||
"currency_scale": 2 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove these.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's still useful to have these optional available to wallet software. They're still optional, though.
|
||
* The sender uses the `ledger_info.currency_scale` to determine the integer amount to include in the ILP packet (e.g. if they want the receiver to receive 10 units of `ledger_info.currency_code` on their ledger, a `ledger_info.currency_scale` value of 2 would indicate they should set the `amount` to 1000). In cases where the sender knows the integer amount the receiver should get, for example if that amount was requested by the receiver out of band, the sender does not need to use `ledger_info.currency_code` and `ledger_info.currency_scale` | ||
* The sender SHOULD NOT set an amount greater than the `maximum_destination_amount` or lower than the `minimum_destination_amount`, as this will be rejected by the receiver | ||
In a UI, the `ledger_info` and `receiver_info` objects (if present) can be used for display purposes. These objects can be manipulated by the receiver in any way, so amounts SHOULD be displayed in source units when possible. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove ledger_info
|
||
## Appendix A: (Optional) Webfinger Discovery | ||
The payment pointer is in the form `$example.com/bob` (A payment pointer with no path is also acceptable, i.e. `$bob.example.com`). This is converted into an SPSP URI, by removing the `$` and replacing it with `https://spsp.`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The payment pointer is in the form
$example.com/bob
(A payment pointer with no path is also acceptable, i.e.$bob.example.com
). This is converted into an SPSP URI, by removing the$
and replacing it withhttps://spsp.
contradicts:
$alice.example.com
or$example.com/bob
. This SHOULD be the only kind of SPSP identifier exposed to users.
+- Raw endpoint URI (Not recommended)https://example.com/spsp/alice
.
on line 64.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this hasn't been updated with the result of the conversation between Ben and Adrian in the conversation tab above
10. The fulfillment or rejection packet comes back to the sender. | ||
11. The sender MAY send further payment chunks with PSK2 (repeating steps 4-10). | ||
4. The sender begins sending the payment. | ||
1. The sender uses PSK2 to generate the payment chunk and format additional dthese stepsata intended for the reciever to be sent with the payment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Typos
|
||
## Specification | ||
|
||
The SPSP endpoint is a URI used by the sender to query information about the receiver and set up payments. The SPSP endpoint URI MAY contain query string parameters. The sender SHOULD treat the URI as opaque. | ||
The SPSP endpoint is a URI used by the sender to query information about the receiver (which may be an invoice) and set up payments. The SPSP endpoint URI MUST NOT contain query string parameters. The sender SHOULD treat the URI as opaque. There are several supported ways to refer to an SPSP endpoint: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why can't the spsp uri contain query parameters?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems like a strange way to use the identifier. Visually, keeping special characters down is nice for readability. Forbidding reserved characters also lets people pass around payment-pointers like https://wallet.example.com/?receiver=$bob.example.com
without worrying about escaping. It also creates some more complexity in how we resolve the identifier by adding more moving parts. Does $example.com?foo=bar
resolve to https://example.com/.well-known/pay?foo=bar
or https://example.com/?foo=bar
? It would also preclude us from adding any query parameters as part of the resolution protocol, if we did that sometime in the future.
I don't think any of those are super strong reasons, but I also don't think the benefit is worth it.
* The `amount` is determined by the sender: | ||
* The `destination_account` should be used as the PSK2 destinationAccount. | ||
* The `shared_secret` should be used as the PSK2 sharedSecret. | ||
* If present, the `balance.maximum` SHOULD be used as the PSK2 chunked payment amount. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Specify that it's the destination amount
|
||
## Appendix A: (Optional) Webfinger Discovery | ||
The payment pointer is in the form `$example.com/bob` (A payment pointer with no path is also acceptable, i.e. `$bob.example.com`). This is converted into an SPSP URI, by removing the `$` and replacing it with `https://`. If the payment pointer has no path, then a path of `/.well-known/pay` is added. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems a bit strange that the resolution behavior depends on whether there's a path. Is there a reason not to do something like webfinger where you query the endpoint with the whole identifier?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah, that makes it very difficult to have one identifier that redirects to another. For example if my SPSP receiver is hosted on $sharafian.example.com
and I set $sharafian.com
to redirect there, then example.com will end up with the request https://sharafian.example.com/.well-known/pay?resource=$sharafian.com
, which it won't know what to do with. This was a constant annoyance when we were using webfinger and ILP kit, so I'd be happy if we don't have to re-introduce it.
Having a default path isn't very hard behavior to implement, and I think it isn't so strange to say you use a hard-coded default unless there's a specific path specified in the identifier.
@@ -49,7 +49,7 @@ We assume that the sender knows the receiver's SPSP endpoint (see [Appendix B: P | |||
2. The SPSP Endpoint responds with the receiver info, including the receiver's ILP address and the shared secret to be used in PSK2. It MAY respond with a balance associated with this SPSP receiver, i.e. in the case of an invoice. | |||
3. The sender constructs an ILP payment using the receiver's ILP address. | |||
4. The sender begins sending the payment. | |||
1. The sender uses PSK2 to generate the payment chunk and format additional dthese stepsata intended for the reciever to be sent with the payment. | |||
1. The sender uses PSK2 to generate the payment chunk and format additional data intended for the reciever to be sent with the payment. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
reciever -> receiver
|
||
Whenever possible, receiver URLs should be exchanged out-of-band and discovery should be skipped. However, in some cases, it may be useful to have a standardized user-friendly identifier. This discovery method describes how to resolve such an identifier to an SPSP endpoint. | ||
Any characters allowed in a URL are allowed in a payment pointer, but special characters MUST be properly URL-encoded. The payment pointer MUST NOT have any query string, MUST NOT have any authentication info, and MUST NOT have a trailing slash. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
MUST NOT have any authentication info
It is unclear what "authentication info" is referring to. Assuming you mean the user:pass@host
notation, better stick to the terminology established in RFC 3986 and insert a link. The updated text should say something like: [...] MUST NOT have any user information [...]
|
||
Whenever possible, receiver URLs should be exchanged out-of-band and discovery should be skipped. However, in some cases, it may be useful to have a standardized user-friendly identifier. This discovery method describes how to resolve such an identifier to an SPSP endpoint. | ||
Any characters allowed in a URL are allowed in a payment pointer, but special characters MUST be properly URL-encoded. The payment pointer MUST NOT have any query string, MUST NOT have any authentication info, and MUST NOT have a trailing slash. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Say explicitly that any payment pointer that does not comply with the restrictions listed in this paragraph MUST NOT be translated to an URL.
If implementations translate invalid payment pointers into URLs it will be spoofer's paradise.
|
||
First, the sender uses Webfinger ([RFC 7033](https://tools.ietf.org/html/rfc7033)) to look up an identifier (e.g. `bob@red.ilpdemo.org`): | ||
Adding this subdomain allows you to use `$example.com` as your payment pointer, even if the actual `example.com` is running a website via a CDN like github pages. The SPSP traffic will go to `spsp.example.com`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Adding this subdomain allows [...]
It is not clear to what "this subdomain" refers.
3007828
to
fced52d
Compare
fced52d
to
4683ac0
Compare
I believe all comments are addressed. Can we try to get this merged? |
@sharafian maybe the Appendix about Payment Pointers can be dropped and replaced with a link to the Payment Pointers spec? |
I think you're looking at an old commit; both of those things are gone now |
This is now out of date, because PSK2 has been superseded by ILP/STREAM, right? |
Well it reflects the current implementation so I don't know if I'd call it outdated, but you're right that ILP/STREAM will cause another change to this |
if it describes the current reference implementation, then i think we should just merge it, and maybe move the requested changes to follow-up tickets where necessary? |
@justmoon @emschwartz @dappelt This is blocked on your reviews. Please review again so we can merge |
@justmoon @emschwartz speak now or forever hold your peace |
bob@example.com
, favoring the$bob.example.com
payment-pointer style instead.Accept: application/x-spsp-response
.maximum_destination_amount
andminimum_destination_amount
from response.receiver_info
andledger_info
optional fields from response.balance
object in response withbalance.maximum
andbalance.current
for invoices.$bob.example.com
payment-pointer identifiers.